/**
 * @(#) RemotingCallRmi.java
 * module  : RemotingCallFramework
 * version : 版本管理系统中的文件版本
 * date    : 2008-12-3
 * name    : 马仁配
 */
package com.smartpay.its.framework.remoting.hessian.client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.caucho.hessian.client.HessianProxyFactory;

/**
 * 如果有任何对代码的修改,请按下面的格式注明修改的内容.
 * 
 * 序号 时间 作者 修改内容
 * 
 * 1. 2008-12-3 谢芝伟 created this class.
 * 
 * 2. 2011-9-28 谢芝伟 新增提供自定义超时调用
 */
public class RemotingCallUtil {

	private static final Logger logger = LoggerFactory.getLogger(RemotingCallUtil.class);

	/**
	 * 默认的hessian服务所在的应用服务器地址.
	 */
	public static String host = "http://localhost/payment/index.do?id=";

	/**
	 * 保存远程调用的模块与服务器之间映射关系的属性数据.
	 */
	private static Properties prop;

	private static final int CONNECT_TIMEOUT = 10000;
	private static final int READ_TIMEOUT = 30000;

	/**
	 * 设置连接地址.
	 * 
	 * @param connectionUrl
	 */
	public static void setConnectionUrl(String connectionUrl) {
		RemotingCallUtil.host = connectionUrl;
	}

	/**
	 * 根据需要调用的hessian服务所实现的接口类，创建Hessian调用的客户端.
	 * 
	 * @param <T>
	 * @param serviceInterface
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <V extends Object> V getHessianService(Class<?> serviceInterface) {
		return (V) getHessianService(host, serviceInterface);
	}

	/**
	 * 从指定的连接地址创建hessian调用的客户端.
	 * 
	 * @param <V>
	 * @param connectionUrl
	 * @param serviceInterface
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <V extends Object> V getHessianService(String connectionUrl,
			Class<?> serviceInterface) {
		String url = connectionUrl + serviceInterface.getCanonicalName();
		HessianProxyFactory factory = new HessianProxyFactory();
		factory.setOverloadEnabled(true); // 支持重载
		factory.setConnectTimeout(CONNECT_TIMEOUT);
		factory.setReadTimeout(READ_TIMEOUT);
		logger.info("Hessian service call {}, ConnTimout {}, ReadTimeout {}.", url,
				factory.getConnectTimeout(), factory.getReadTimeout());
		try {
			Object stub = factory.create(serviceInterface, url);
			return (V) stub;
		} catch (MalformedURLException e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 从指定的连接地址创建hessian调用的客户端.<br>
	 * 自定义超时时间
	 * 
	 * @param connectionUrl
	 * @param serviceInterface
	 * @param customizedConnectTimeOut
	 *            尝试连接超时时间，单位毫秒
	 * @param customizedReadTimeOut
	 *            请求等待响应超时时间，单位毫秒
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <V extends Object> V getHessianService(String connectionUrl,
			Class<?> serviceInterface, int customizedConnectTimeOut, int customizedReadTimeOut) {
		String url = connectionUrl + serviceInterface.getCanonicalName();
		HessianProxyFactory factory = new HessianProxyFactory();
		factory.setOverloadEnabled(true); // 支持重载
		if (customizedConnectTimeOut >= 0) {
			factory.setConnectTimeout(customizedConnectTimeOut);
		}
		if (customizedReadTimeOut >= 0) {
			factory.setReadTimeout(customizedReadTimeOut);
		}
		logger.info("Hessian service call {}, ConnTimout {}, ReadTimeout {}.", url,
				factory.getConnectTimeout(), factory.getReadTimeout());
		try {
			Object stub = factory.create(serviceInterface, url);
			return (V) stub;
		} catch (MalformedURLException e) {
			logger.error(e.getMessage());
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public static <V extends Object> V getHessianServiceByHost(String host, String module,
			Class<?> serviceInterface) {
		StringBuffer buf = new StringBuffer();
		buf.append("http://").append(host).append('/').append(module).append("/index.do?id=");
		return (V) getHessianService(buf.toString(), serviceInterface);
	}

	/**
	 * 根据模块名获取该模块下的远程调用hessian服务. 这个模块名是在remoting.properties文件中定义的key
	 * 例如：ms-app=192.168.121.128，模块名为ms-app
	 * 
	 * @param <V>
	 * @param module
	 * @param serviceInterface
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <V extends Object> V getHessianServiceByModule(String module,
			Class<?> serviceInterface) {
		loadRemotingConfiguration();
		StringBuffer buf = new StringBuffer();
		buf.append("http://").append(prop.getProperty(module)).append('/').append(module)
				.append("/index.do?id=");
		return (V) getHessianService(buf.toString(), serviceInterface);
	}

	/**
	 * 根据模块名获取该模块下的远程调用hessian服务. 这个模块名是在remoting.properties文件中定义的key
	 * 例如：ms-app=192.168.121.128，模块名为ms-app
	 * 
	 * 自定义超时时间
	 * 
	 * @param <V>
	 * @param module
	 * @param serviceInterface
	 * @param customizedConnectTimeOut
	 *            尝试连接超时时间，单位毫秒
	 * @param customizedReadTimeOut
	 *            请求等待响应超时时间，单位毫秒
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <V extends Object> V getHessianServiceByModule(String module,
			Class<?> serviceInterface, int customizedConnectTimeOut, int customizedReadTimeOut) {
		loadRemotingConfiguration();
		StringBuffer buf = new StringBuffer();
		buf.append("http://").append(prop.getProperty(module)).append('/').append(module)
				.append("/index.do?id=");
		return (V) getHessianService(buf.toString(), serviceInterface, customizedConnectTimeOut,
				customizedReadTimeOut);
	}

	@SuppressWarnings("unchecked")
	public static <V extends Object> V getIndHessianServiceByModule(String module,
			Class<?> serviceInterface) {
		loadRemotingConfiguration();
		StringBuffer buf = new StringBuffer();
		buf.append("http://").append(prop.getProperty(module)).append('/').append(module)
				.append("/index.hsdo?id=");
		return (V) getHessianService(buf.toString(), serviceInterface);
	}

	/**
	 * 从配置文件中加载远程调用的配置数据. 模块=服务器地址 用于说明指定模块的远程调用是从该服务器地址上发起调用.
	 */
	private static void loadRemotingConfiguration() {
		if (null == prop || prop.isEmpty()) {
			prop = new Properties();
			try {
				prop.load(RemotingCallUtil.class.getClassLoader().getResourceAsStream(
						"properties/remoting.properties"));
			} catch (IOException e) {
				logger.error(e.getMessage(), e);
			}
		}
	}
}
